#pragma once
#include <atomic>
#include <cassert>
#include <cerrno>
#include <cstdint>
#include <cstdlib>  // atexit
#include <cstring>
#include <memory>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
#include "XnccType.h"
#if defined(__CYGWIN__)
#    include <XnccEventfd.h>
#else
#    include <sys/eventfd.h>
#endif

namespace xncc {
namespace shared {
// 非两次  保证表达式是bool
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)

#define smp_rmb() __asm__ __volatile__("" ::: "memory")
#define smp_wmb() __asm__ __volatile__("" ::: "memory")

#define mybasename(file) (strrchr(file, '/') ? (strrchr(file, '/') + 1) : file)

    const char* strerror_tl(int savedErrno);

    std::string getDisconnectedReason(int err);

    template <typename T, typename... Args>
    auto createUniquePtr(Args&&... args) -> std::unique_ptr<T>
    {
#if __cplusplus >= 201402L
        return std::make_unique<T>(std::forward<Args>(args)...);
#else
        return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
#endif
    }

    template <typename T>
    void memZero(T& obj)
    {
        memset(&obj, 0, sizeof(obj));
    }

    template <typename T>
    void memZero(T* ptr)
    {
        std::memset(ptr, 0, sizeof(T));
    }

    inline std::string concatToString() { return ""; }

    template <typename T>
    std::string concatToString(const T& arg)
    {
        std::ostringstream oss;
        oss << arg;
        return oss.str();
    }

    template <typename T, typename... Args>
    std::string concatToString(const T& first, const Args&... args)
    {
        std::ostringstream oss;
        oss << first;
        // 递归调用自身，处理剩余的参数
        oss << concatToString(args...);
        return oss.str();
    }

    struct CommonBusi
    {
        static int                    setCpuAffinity(int coreId);
        static int                    createTimerfd();
        static int64_t                generateSeqNo();
        static types::connection_id_t generateConnId();
        static bool                   isIpV4(const std::string& ip);
        static bool                   isIpV6(const std::string& ip);

        template <typename T>
        static std::string vectorToString(const std::vector<T>& vec)
        {
            std::ostringstream oss;
            for (auto& v : vec) {
                oss << v << " ";
            }
            return oss.str();
        }

        static bool is_power_of_2(uint64_t n) { return (n != 0 && ((n & (n - 1)) == 0)); }

        static uint64_t roundup_pow_of_two(uint64_t n)
        {
            n |= n >> 1;
            n |= n >> 2;
            n |= n >> 4;
            n |= n >> 8;
            n |= n >> 16;
            n |= n >> 32;
            n += 1;
            return n;
        }

        static uint64_t rounddown_pow_of_two(uint64_t n) { return roundup_pow_of_two(n) >> 1; }

        static std::atomic<int64_t>                gSeqNo;
        static std::atomic<types::connection_id_t> gConnId;
    };

    template <typename To, typename From>
    inline To implicit_cast(From const& f)
    {
        return f;
    }

    struct FileBusi
    {
        static void        createPath(const std::string& path);
        static std::string appendPath(const std::string& path, const std::string& file);
        static bool        exists(const std::string& file);
        static bool        isLink(const std::string& file);
        static bool        isDirectory(const std::string& file);
        static bool        isFile(const std::string& file);
        static void        remove(const std::string& file);

      private:
        static bool isSpecificMode(const std::string& file, mode_t mode);
    };

    struct logic_exception : public std::logic_error
    {
        explicit logic_exception(const std::string& what = "") : std::logic_error("logic error:" + what) {}
    };

    struct system_exception : public std::logic_error
    {
        explicit system_exception(const std::string& what = "")
            : std::logic_error("system error:" + what + " " + strerror_tl(errno))
        {
        }
    };

    template <typename T>
    constexpr T ROUND_UP(T value, T align)
    {
        static_assert(std::is_integral<T>::value, "T must be an integral type");
        return (value + align - 1) / align * align;
    }

    struct StrBusi
    {
        static std::vector<std::string> split(const std::string& str, const std::string& pattern);
        static std::string              toUpper(const std::string& str);
        static std::string              toLower(const std::string& str);
    };

}  // namespace shared
}  // namespace xncc
